﻿namespace Sai.Core
{
    using Sai.Core.Introspection;
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Linq;

    internal sealed class ExactMatchComparer<T> : IEqualityComparer<T>
        where T : IExactlyMatch<T> 
    {
        public bool Equals(T first, T second)
        {
            return first.ExactMatchFor(second);
        }

        public int GetHashCode(T obj)
        {
            // Force Equals comparison (emartin).
            return 1;
        }
    }

	public static class TypeMemberMatcher
	{
        public static Collection<T> FindRemovedMembers<T>(this IEnumerable<T> later, IEnumerable<T> earlier)
			where T : IExactlyMatch<T> 
		{
            Collection<T> removed = new Collection<T>();

			foreach (var item in earlier)
			{
				if (!later.ContainsExactMatch(item))
				{
					removed.Add(item);
				}
			}

			return removed;
		}

        public static Collection<T> FindAddedMembers<T>(this IEnumerable<T> later, IEnumerable<T> earlier)
            where T : IExactlyMatch<T> 
        {
            Collection<T> added = new Collection<T>();
            
            foreach (var item in later)
            {
                if (!earlier.ContainsExactMatch(item))
                {
                    added.Add(item);
                }
            }

            return added;
        }

        public static Collection<T> FindObsoleteMembers<T>(this IEnumerable<T> later)
			where T : ITypeMember 
		{
            Collection<T> obsolete = new Collection<T>();

			foreach (var item in later)
			{
				if (item.IsObsolete)
				{
					obsolete.Add(item);
				}
			}

			return obsolete;
		}

        public static Collection<Tuple<T, T>> FindMatchingMembers<T>(this IEnumerable<T> later, IEnumerable<T> earlier)
            where T : ITypeMember, ILooselyMatch<T> 
        {
            var matches = new Collection<Tuple<T, T>>();

            foreach (var item in earlier)
            {
                T match = later.LooseMatchFor(item);

                if (match != null)
                {
                    matches.Add(new Tuple<T, T>(item, match));
                }
            }

            return matches;
        }

//				code.Earlier.Add(item.ToString());

				//if (later.ContainsRoughMatch(item))
				//{
				//    var match = later.RoughMatch(item);

				//    if (match != null && !match.ExactMatch(item))
				//    {
				//        if (reportingOptions.ReportOnChanges)
				//        {
				//            code.Add(match.DifferenceFrom(item));
				//        }
				//    }
				//}
				//else
				//{
				//        removed...
				//    if (reportingOptions.ReportOnRemovals)
				//    {
				//        code.Add(item.Removal);
				//    }
				//}
			//}
			//foreach (var item in later)
			//{
			//    if (!earlier.ContainsExactMatch(item))
			//    {
			//        string message = string.Format("{0} added", item);
			//        //walker.AddChange(new Change(message, ChangeCategory.NonBreaking, ChangeLevel.Member));
			//    }

			//    //code.Later.Add(item.ToString());

			//    //if (!earlier.ContainsRoughMatch(item))
			//    //{
			//    //        added...
			//    //    if (reportingOptions.ReportOnAdditions)
			//    //    {
			//    //        code.Add(item.Addition);
			//    //    }
			//    //}
			//}
	}

    public static class MethodMatcher
    {
        /// <summary>
        /// Returns a new list of items that exist in first but not exactly matched in second
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="first"></param>
        /// <param name="second"></param>
        /// <returns></returns>
        public static Collection<T> RemoveExactMatches<T>(this IEnumerable<T> first, IEnumerable<T> second)
            where T : ITypeMember, IExactlyMatch<T>
        {
            var existInFirst = new Collection<T>();

            foreach (var item in first)
            {
                T match = second.ExactMatchFor(item);

                if (match == null)
                {
                    existInFirst.Add(item);
                }
            }

            return existInFirst;
        }
    }

}

//using System;
//using System.Collections.Generic;
//using System.Linq;
//using System.Text;
//using System.Diagnostics;

//namespace Sai.Core
//{
//    public static class RoughMatcher
//    {
//        public static bool ContainsRoughMatch<T>(this IEnumerable<T> data, T matchFor)
//                                                where T : IRoughlyMatch<T>
//        {
//            bool roughMatch = false;

//            foreach (T item in data)
//            {
//                if (item.RoughMatch(matchFor))
//                {
//                    roughMatch = true;
//                    break;
//                }
//            }

//            return roughMatch;
//        }

//        public static T RoughMatch<T>(this IEnumerable<T> data, T matchFor)
//                                        where T : IRoughlyMatch<T>
//        {
//            foreach (T item in data)
//            {
//                if (item.RoughMatch(matchFor))
//                    return item;
//            }

//            return default(T);
//        }

//        public static IEnumerable<T> RoughMatches<T>(this IEnumerable<T> data, T matchFor)
//                                        where T : IRoughlyMatch<T>
//        {
//            foreach (T item in data)
//            {
//                if (item.RoughMatch(matchFor)) yield return item;
//            }
//        }

//        public static CodeElement DifferencesFrom<T>(this IEnumerable<T> later, IEnumerable<T> earlier)
//            where T : IRoughlyMatch<T>, IExactlyMatch<T>, ICodeDifference<T>
//        {
//            return later.DifferencesFrom(earlier, new AnalysisOptions());
//        }

//         return some sort of difference type...
//        public static CodeElement DifferencesFrom<T>(this IEnumerable<T> later, IEnumerable<T> earlier, AnalysisOptions reportingOptions)
//            where T : IRoughlyMatch<T>, IExactlyMatch<T>, ICodeDifference<T>
//        {
//            var code = new CodeElement();

//            foreach (var item in earlier)
//            {
//                code.Earlier.Add(item.ToString());

//                if (later.ContainsRoughMatch(item))
//                {
//                    var match = later.RoughMatch(item);

//                    if (match != null && !match.ExactMatch(item))
//                    {
//                        if (reportingOptions.ReportOnChanges)
//                        {
//                            code.Add(match.DifferenceFrom(item));
//                        }
//                    }
//                }
//                else
//                {
//                     removed...
//                    if (reportingOptions.ReportOnRemovals)
//                    {
//                        code.Add(item.Removal);
//                    }
//                }
//            }

//            foreach (var item in later)
//            {
//                code.Later.Add(item.ToString());

//                if (!earlier.ContainsRoughMatch(item))
//                {
//                     added...
//                    if (reportingOptions.ReportOnAdditions)
//                    {
//                        code.Add(item.Addition);
//                    }
//                }
//            }

//            return code;
//        }
//    }

//}
